package org.dawfinn.droiditarian.client.admin;

import java.util.HashMap;
import java.util.Map;


import com.google.gwt.core.client.EntryPoint;
import com.google.gwt.core.client.GWT;
import com.google.gwt.event.dom.client.ClickEvent;
import com.google.gwt.event.dom.client.ClickHandler;
import com.google.gwt.user.client.Cookies;
import com.google.gwt.user.client.Window;
import com.google.gwt.user.client.rpc.AsyncCallback;
import com.google.gwt.user.client.ui.Button;
import com.google.gwt.user.client.ui.DialogBox;
import com.google.gwt.user.client.ui.FlexTable;
import com.google.gwt.user.client.ui.Label;
import com.google.gwt.user.client.ui.PasswordTextBox;
import com.google.gwt.user.client.ui.RootPanel;
import com.google.gwt.user.client.ui.TextBox;

public class Admin_server implements EntryPoint {

	FlexTable deedsTable;
	Map<String, ClientDeed> deeds = new HashMap<String, ClientDeed>();
	TextBox key;
	TextBox name;
	TextBox description;
	TextBox explanation;
	TextBox moreInfo;
	TextBox releaseDate;
	Button clearEditFields;
	Button submitDeed;

	TextBox email;
	PasswordTextBox password;
	Button submitLogin;

	TextBox newEmail;
	PasswordTextBox newPassword;
	Button submitNewUser;

	RootPanel content;
	RootPanel login;

	String sid = "test";

	private static final String SID_COOKIE = "sid";
	private static final String DATE_FORMAT = "MM/DD/YY HH:MM (AM|PM)";

	private final DeedsServiceAsync deedsService = GWT.create(DeedsService.class);
	private final LoginServiceAsync loginService = GWT.create(LoginService.class);

	public void onModuleLoad() {
		deedsTable = new FlexTable();

		email = new TextBox();
		RootPanel.get("email").add(email);
		password = new PasswordTextBox();
		RootPanel.get("password").add(password);
		submitLogin = new Button("Login");
		RootPanel.get("submitLogin").add(submitLogin);
		submitLogin.addClickHandler(new ClickHandler() {

			public void onClick(ClickEvent event) {
				loginService.login(email.getText(), password.getText(), new AsyncCallback<String>() {

					public void onFailure(Throwable caught) {
						Window.alert("Login failed.");
					}

					public void onSuccess(String result) {
						Window.alert("Login succeeded!");
						Cookies.setCookie(SID_COOKIE, result);
						sid = result;
						login.setVisible(false);
						content.setVisible(true);
						initContent();
					}
				});
				email.setText("");
				password.setText("");
			}
		});

		key = new TextBox();
		key.setEnabled(false);
		RootPanel.get("key").add(key);
		name = new TextBox();
		RootPanel.get("name").add(name);
		description = new TextBox();
		RootPanel.get("description").add(description);
		explanation = new TextBox();
		RootPanel.get("explanation").add(explanation);
		moreInfo = new TextBox();
		RootPanel.get("moreInfo").add(moreInfo);
		releaseDate = new TextBox();
		releaseDate.setText(DATE_FORMAT);
		RootPanel.get("releaseDate").add(releaseDate);

		submitDeed = new Button("Submit Changes");
		submitDeed.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				submitChanges();
			}
		});
		RootPanel.get("submit").add(submitDeed);

		clearEditFields = new Button("Clear Edit Fields");
		clearEditFields.addClickHandler(new ClickHandler() {
			public void onClick(ClickEvent event) {
				clearEditFields();
			}
		});
		RootPanel.get("refreshEditDataContainer").add(clearEditFields);

		deedsTable = new FlexTable();
		RootPanel.get("list").add(deedsTable);

		newEmail = new TextBox();
		RootPanel.get("newEmail").add(newEmail);
		newPassword = new PasswordTextBox();
		RootPanel.get("newPassword").add(newPassword);
		submitNewUser = new Button("Create new user");
		RootPanel.get("submitNewUser").add(submitNewUser);
		submitNewUser.addClickHandler(new ClickHandler() {

			public void onClick(ClickEvent event) {
				loginService.createUser(newEmail.getText(), newPassword.getText(), new AsyncCallback<Boolean>() {

					public void onFailure(Throwable caught) {
						Window.alert("New User Creation Failed");
					}

					public void onSuccess(Boolean result) {
						if (result)
						Window.alert("New User Created Successfully");
						else
							Window.alert("New User Creation Failed");
					}
				});
			}
		});

		login = RootPanel.get("login");
		login.setVisible(false);
		content = RootPanel.get("content");
		content.setVisible(false);

		sid = Cookies.getCookie(SID_COOKIE);
		if (sid != null) {
			loginService.verifySid(sid, new AsyncCallback<Boolean>() {

				public void onFailure(Throwable caught) {
					login.setVisible(true);
				}

				public void onSuccess(Boolean result) {
					initContent();
					content.setVisible(true);
				}
			});
		} else {
			login.setVisible(true);
		}
	}

	private void initContent() {
		deedsService.getDeeds(sid, new AsyncCallback<ClientDeed[]>() {

			public void onSuccess(ClientDeed[] result) {
				deeds.clear();
				for (ClientDeed d : result) {
					deeds.put(d.getKey(), d);
				}
				updateTable();
			}

			public void onFailure(Throwable caught) {
				DialogBox error = new DialogBox();
				error.add(new Label("Unable to download deeds."));
			}
		});
	}

	private void submitChanges() {
		if (key.getText() == null || "".equals(key.getText())) {

			deedsService.createDeed(name.getText(), description.getText(), explanation.getText(), moreInfo.getText(), releaseDate.getText(), sid,
			        new AsyncCallback<ClientDeed>() {

				        public void onFailure(Throwable caught) {
					        DialogBox error = new DialogBox();
					        error.add(new Label("Deed submission failed."));
					        error.show();
				        }

				        public void onSuccess(ClientDeed result) {
					        deeds.put(result.getKey(), result);
					        updateTable();
				        }
			        });
		} else {
			deedsService.editDeed(key.getText(), name.getText(), description.getText(), explanation.getText(), moreInfo.getText(), releaseDate
			        .getText(), sid, new AsyncCallback<ClientDeed>() {

				public void onFailure(Throwable caught) {
					DialogBox error = new DialogBox();
					error.add(new Label("Deed submission failed."));
					error.show();
				}

				public void onSuccess(ClientDeed result) {
					deeds.put(result.getKey(), result);
					updateTable();
				}
			});
		}
		clearEditFields();
	}

	private void clearEditFields() {
		key.setText("");
		name.setText("");
		description.setText("");
		explanation.setText("");
		moreInfo.setText("");
		releaseDate.setText("");
	}

	public void updateTable() {
		int row = 0, col = 0;
		Button editButton, deleteButton;
		deedsTable.clear(true);
		deedsTable.setText(row, col++, "Key");
		deedsTable.setText(row, col++, "Name");
		deedsTable.setText(row, col++, "Description");
		deedsTable.setText(row, col++, "Explanation");
		deedsTable.setText(row, col++, "More Info");
		deedsTable.setText(row, col++, "Release Date");
		deedsTable.setText(row, col++, "Completed Count");
		deedsTable.setText(row, col++, "Favorite Count");
		deedsTable.setText(row, col++, "Edit");
		deedsTable.setText(row, col++, "Delete");
		row++;
		for (ClientDeed d : deeds.values()) {
			col = 0;
			deedsTable.setText(row, col++, d.getKey());
			deedsTable.setText(row, col++, d.getName());
			deedsTable.setText(row, col++, d.getDescription());
			deedsTable.setText(row, col++, d.getExplanation());
			deedsTable.setText(row, col++, d.getMoreInfo());
			deedsTable.setText(row, col++, d.getReleaseDate());
			deedsTable.setText(row, col++, "" + d.getCompletedCount());
			deedsTable.setText(row, col++, "" + d.getFavoriteCount());
			editButton = new Button("Edit");
			editButton.addClickHandler(new EditDeedButtonHandler(d));
			deedsTable.setWidget(row, col++, editButton);
			deleteButton = new Button("Delete");
			deleteButton.addClickHandler(new DeleteDeedButtonHandler(d));
			deedsTable.setWidget(row, col++, deleteButton);
			row++;
		}
	}

	private class EditDeedButtonHandler implements ClickHandler {
		private final ClientDeed deed;

		public EditDeedButtonHandler(ClientDeed d) {
			this.deed = d;
		}

		public void onClick(ClickEvent event) {
			key.setText(deed.getKey());
			name.setText(deed.getName());
			description.setText(deed.getDescription());
			explanation.setText(deed.getExplanation());
			moreInfo.setText(deed.getMoreInfo());
			releaseDate.setText(deed.getReleaseDate());
		}
	}

	private class DeleteDeedButtonHandler implements ClickHandler, AsyncCallback<Boolean> {
		private final ClientDeed deed;

		public DeleteDeedButtonHandler(ClientDeed d) {
			this.deed = d;
		}

		public void onClick(ClickEvent event) {
			deedsService.deleteDeed(deed.getKey(), sid, this);
		}

		public void onFailure(Throwable caught) {

		}

		public void onSuccess(Boolean result) {
			if (result) {
				deeds.remove(deed.getKey());
				updateTable();
			}
		}
	}
}
